﻿#region License...
/*
Copyright (c) 2005-2009, CellAO Team

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    * Neither the name of the CellAO Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#endregion

#region Usings..
using System;
using System.Collections.Generic;
using System.Text;
using AO.Core;
#endregion

namespace ZoneEngine.NPC
{

    public class RunningNano
    {
        #region RunningNano
        public int Nanotype { get; set; }
        public int Instance { get; set; }
        public int Value3 { get; set; }
        public int Time1 { get; set; }
        public int Time2 { get; set; }
        #endregion
    }

    public class MobMesh
    {
        #region MobMesh
        // Name not needed
        public int Meshvalue1 { get; set; }
        public int Meshvalue2 { get; set; }
        public int Meshvalue3 { get; set; }
        #endregion
    }

    public class Weaponpair
    {
        #region Weaponpair
        public int value1 { get; set; }
        public int value2 { get; set; }
        public int value3 { get; set; }
        public int value4 { get; set; }
        #endregion
    }

    public class AdditionalMesh
    {
        #region AdditionalMesh
        public byte position { get; set; }
        public int meshvalue1 { get; set; }
        public int meshvalue2 { get; set; }
        public byte priority { get; set; }
        #endregion
    }


	public class Monster
    {
        #region Stats
        public int ID { get; set; }
        public int Playfield { get; set; }
        public AOCoord coord { get; set; }
        public Quaternion heading { get; set; }
        public int Side { get; set; }
        public int Fatness { get; set; }
        public int Breed { get; set; }
        public int Sex { get; set; }
        public int Race { get; set; }
        public string Name { get; set; }
        public int Flags { get; set; }
        public int NPCFamily { get; set; }
        public int Level { get; set; }
        public int Health { get; set; }
        public int Damage { get; set; }
        public int MonsterData { get; set; }
        public int MonsterScale { get; set; }
        public int HeadMesh { get; set; }
        public int Runspeed { get; set; }
        public int unknown1 { get; set; }
        public int unknown2 { get; set; }
        public int unknown3 { get; set; }
        public int TextureHands { get; set; }
        public int TextureBody { get; set; }
        public int TextureFeet { get; set; }
        public int TextureArms { get; set; }
        public int TextureLegs { get; set; }
        public int LOSHeight { get; set; }
        public int Attacking { get; set; }
        public List<MobMesh> MobMeshs;
        public List<RunningNano> RunningNanos;
        public List<AOCoord> Waypoints;
        public List<Weaponpair> Weaponpairs;
        public List<AdditionalMesh> AdditionalMeshs;
        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the Monster class.
        /// </summary>
        /// <returns></returns>
        public Monster()
        {
            ID = 0;
            Playfield = 0;
            coord = new AOCoord(0.0f, 0.0f, 0.0f);
            heading = new Quaternion(0.0, 0.0, 0.0, 0.0);
            Side = 0;
            Fatness = 0;
            Breed = 0;
            Sex = 0;
            Race = 0;
            Name = "";
            Flags = 0;
            NPCFamily = 0;
            Level = 0;
            Health = 0;
            MonsterData = 0;
            MonsterScale = 0;
            TextureHands = 0;
            TextureBody = 0;
            TextureFeet = 0;
            TextureArms = 0;
            TextureLegs = 0;
            Runspeed = 0;
            Damage = 0;
            HeadMesh = 0;
            Attacking = 0;
            MobMeshs = new List<MobMesh>();
            RunningNanos = new List<RunningNano>();
            Waypoints = new List<AOCoord>();
            Weaponpairs = new List<Weaponpair>();
            AdditionalMeshs = new List<AdditionalMesh>();
            unknown1 = 0;
            unknown2 = 0;
            unknown3 = 0;
        }

        /// <summary>
        /// Initializes a new instance of the Monster class.
        /// </summary>
        /// <param name="cli"></param>
        /// <param name="hash">Hash of NPC</param>
        /// <param name="level">Level of NPC</param>
        public Monster(Client cli, string hash, int level)
        {
            bool found = false;
            int tmpID = 100000;
            int minLvl = 1, maxLvl = 255;
            byte[] blobread = new byte[2048];
            byte[] bytetodouble = new byte[4];
            long retval;
            long counter;
            int value1, value2, value3;
            MobMesh temp;
            AdditionalMesh tempm;
            MobMeshs = new List<MobMesh>();
            RunningNanos = new List<RunningNano>();
            Waypoints = new List<AOCoord>();
            Weaponpairs = new List<Weaponpair>();
            AdditionalMeshs = new List<AdditionalMesh>();
            foreach (NPC2 mMonster in Program.zoneServer.Monsters)
            {
                if (mMonster.ID <= tmpID) continue;
                tmpID = mMonster.ID;
            }
            tmpID += 1;
            MySqlWrapper msql = new MySqlWrapper();
            msql.MySqlRead(string.Format("SELECT * FROM `mobtemplate` WHERE Hash =  '{0}'", hash));
            while (msql.myreader.Read())
            {
                ID = tmpID;
                Playfield = cli.Character.PlayField;
                coord = cli.Character.Coordinates;
                heading = cli.Character.Heading;
                Side = msql.myreader.GetInt32("Side");
                Fatness = msql.myreader.GetInt32("Fatness");
                Breed = msql.myreader.GetInt32("Breed");
                Sex = msql.myreader.GetInt32("Sex");
                Race = msql.myreader.GetInt32("Race");
                Name = msql.myreader.GetString("Name");
                Flags = msql.myreader.GetInt32("Flags");
                NPCFamily = msql.myreader.GetInt32("NPCFamily");
                minLvl = msql.myreader.GetInt32("MinLvl");
                maxLvl = msql.myreader.GetInt32("MaxLvl");

                // Reading Meshblob
                // fieldcount-2
                retval = msql.myreader.GetBytes(msql.myreader.FieldCount - 2, 0, blobread, 0, 2047);
                counter = 0;
                while (counter < retval - 1)
                {
										
                    // Read values and reverse them
                    value1 = BitConverter.ToInt32(blobread, (int)counter);
                    value2 = BitConverter.ToInt32(blobread, (int)counter+4);
                    value3 = BitConverter.ToInt32(blobread, (int)counter+8);

                    // Store Mesh into List
                    temp = new MobMesh();
                    temp.Meshvalue1 = value1;
                    temp.Meshvalue2 = value2;
                    temp.Meshvalue3 = value3;

                    MobMeshs.Add(temp);
                    counter += 3 * 4;
                }

                // Reading the additional Meshes (Weapons/Helmets/Glasses and so on)
                retval = msql.myreader.GetBytes(msql.myreader.FieldCount - 1, 0, blobread, 0, 2047);
                counter = 0;
                while (counter < retval - 1)
                {
                    // Read values and reverse them
                    value1 = BitConverter.ToInt32(blobread, (int)counter);
                    value2 = BitConverter.ToInt32(blobread, (int)counter+4);

                    // Store Mesh into List
                    tempm = new AdditionalMesh();
                    tempm.position = blobread[counter+0];
                    tempm.meshvalue1 = value1;
                    tempm.meshvalue2 = value2;
                    tempm.priority = blobread[counter+9];
                    AdditionalMeshs.Add(tempm);
                    counter += 10;
                }



                if ((level < minLvl) || (level > maxLvl))
                {
                    level = new Random().Next(minLvl, maxLvl);
                }
                Level = level;
                Health = msql.myreader.GetInt32("Health");
                MonsterData = msql.myreader.GetInt32("MonsterData");
                MonsterScale = msql.myreader.GetInt32("MonsterScale");
                TextureHands = msql.myreader.GetInt32("TextureHands");
                TextureBody = msql.myreader.GetInt32("TextureBody");
                TextureFeet = msql.myreader.GetInt32("TextureFeet");
                TextureArms = msql.myreader.GetInt32("TextureArms");
                TextureLegs = msql.myreader.GetInt32("TextureLegs");
                HeadMesh = msql.myreader.GetInt32("HeadMesh");

                
                found = true;
            }
            msql.myreader.Close();
            msql.mcc.Close();
            if (!found)
            {
                cli.SendChatText(string.Format("NPC with hash {0} not found!", hash));
            }
        }
        #endregion

        /// <summary>
        /// Despawns this NPC.
        /// </summary>
        /// <param name="cli"></param>
        public void Despawn()
        {
            PacketWriter dspawn = new PacketWriter();
            dspawn.PushByte(0xDF); dspawn.PushByte(0xDF);
            dspawn.PushShort(10);
            dspawn.PushShort(1);
            dspawn.PushShort(0);
            dspawn.PushInt(3086);
            dspawn.PushInt(0);
            dspawn.PushInt(0x36510078);
            dspawn.PushIdentity(50000, ID);
            dspawn.PushByte(1);
            byte[] dspawnA = dspawn.Finish();
            Misc.Announce.Playfield(Playfield, ref dspawnA);
            RemoveFromCache();
        }

        /// <summary>
        /// Spawns this NPC to given client.
        /// </summary>
        /// <param name="cli"></param>
        public void SpawnToClient(Client cli)
        {
            PacketWriter spawn = new PacketWriter();
            int counter,counter2;
            int packetflags = 0x01;  // We want to spawn a NPC
            packetflags |= 0x200;    // Heading flag
            packetflags |= 0x40;     // packet has playfield
            packetflags |= 0x1000;   // push level as 2 byte
            packetflags |= 0x2000;   // runspeed 2 byte also
            if (LOSHeight <= 255)    
            {
                packetflags |= 0x80000;  // LOS Height 1 byte
            }

            if (Attacking != 0)
            {
                packetflags |= 0x400;
            }

            //packetflags |= 0x2;
            packetflags |= 0x2000000;
            packetflags |= 0x200000;



            spawn.PushByte(0xDF);
            spawn.PushByte(0xDF);
            spawn.PushShort(10);
            spawn.PushShort(1);
            spawn.PushShort(0); // Length, packetwriter will take care of this
            spawn.PushInt(3086);
            spawn.PushInt(cli.Character.ID);
            spawn.PushInt(0x271B3A6B);
            spawn.PushIdentity(50000, ID);
            spawn.PushByte(0);
            spawn.PushByte(0x39); // version 0x39
            spawn.PushInt(packetflags);   // packetflags
            spawn.PushInt(Playfield);
            spawn.PushCoord(coord);
            spawn.PushQuat(heading);
            spawn.PushInt(Side + (Fatness * 8) + (Breed * 32) + (Sex * 256) + (Race * 1024));
            spawn.PushByte((byte)(Name.Length + 1));
            spawn.PushBytes(Encoding.ASCII.GetBytes(Name));
            spawn.PushByte(0);
            spawn.PushInt(Flags);
            spawn.PushShort(0); // AccountFlags
            spawn.PushShort(0); // Expansion
            if (NPCFamily <= 127)
            {
                packetflags |= 0x20000;  // NPC Family 1 byte
                spawn.PushByte((byte)NPCFamily);
            }
            else
            {
                packetflags &= ~0x20000;  // NPC Family 2 byte
                spawn.PushShort((short)NPCFamily);
            }

            spawn.PushByte(0);
            spawn.PushByte(0);
            spawn.PushShort(0);


						// TODO: set packetflag for levelsize
            spawn.PushShort((short)Level);

						// TODO: set packetflag for Healthsize/damagesize
            spawn.PushInt(Health);
            spawn.PushInt(Health>>1);  // Health left?? (same Size as Health, flag for 1byte not set)

            // If NPC is in grid or fixer grid
            // make him look like nice upside down pyramid
            if ((Playfield == 152) || (Playfield == 4107))
            {
                spawn.PushInt(99902);
            }
            else
            {
                spawn.PushInt(MonsterData);
            }            
            
            spawn.PushShort((short)MonsterScale);
            spawn.PushShort(0x1F);  // VisualFlags
            spawn.PushByte(0);  // Visible title?
            spawn.PushInt(0x1C);
            spawn.PushInt(unknown1);  // KNUBOT values?
            spawn.PushInt(unknown2);
            spawn.PushInt(unknown3);

						// TODO: Movement Modes
            spawn.PushByte(1);  // CurrentMovementMode
            spawn.PushByte(1);  // Don't change
            spawn.PushShort(1);
            spawn.PushShort(1);
            spawn.PushShort(1);
            spawn.PushShort(1);
            spawn.PushShort(0);
            spawn.PushShort(2);
            spawn.PushShort(0);

            if (HeadMesh != 0)
            {
                packetflags |= 0x80;
                spawn.PushInt(HeadMesh);
            }

						// TODO: runspeedsize+flag
            spawn.PushShort((short)Runspeed); // RunSpeed

            if (Attacking != 0)
            {
                spawn.PushInt(0xc350);
                spawn.PushInt(Attacking);
            }

            if (MobMeshs.Count > 0)
            {
                packetflags |= 0x10;    // Meshs on mob
                spawn.Push3F1Count(MobMeshs.Count);
                for (counter = 0; counter < MobMeshs.Count; counter++)
                {

										// Name for meshtemplate not needed, sending 32byte 00 instead, thx to Suiv
                    for (counter2 = 0; counter2 < 8; counter2++)
                    {
                        spawn.PushInt(0);
                    }
                    spawn.PushInt(MobMeshs[counter].Meshvalue1);
                    spawn.PushInt(MobMeshs[counter].Meshvalue2);
                    spawn.PushInt(MobMeshs[counter].Meshvalue3);
                }

            }

			// Running Nanos/Nano Effects

            /// Running Nanos has to be rewritten.
            /// its not all active nanos on a mob, only the ones client should see
            /// depending on pet status flag and possibly more

            spawn.Push3F1Count(RunningNanos.Count);  
            for (counter = 0; counter < RunningNanos.Count; counter++)
            {
                spawn.PushInt(RunningNanos[counter].Nanotype);
                spawn.PushInt(RunningNanos[counter].Instance);
                spawn.PushInt(RunningNanos[counter].Value3);    
                spawn.PushInt(RunningNanos[counter].Time1);
                spawn.PushInt(RunningNanos[counter].Time2);
            }

            if (Waypoints.Count>0)
            {
                packetflags |= 0x10000; // Waypoints
                spawn.PushInt(0xc350);
                spawn.PushInt(ID);
                spawn.Push3F1Count(Waypoints.Count);  // Waypoints
                for (counter = 0; counter < Waypoints.Count; counter++)
                {
                    spawn.PushCoord(Waypoints[counter]);
                }
            }

            /// Textures have to be rewritten too
            /// mobs should get a equip table
            /// and derive the textures from the equipped items

            spawn.Push3F1Count(5);  // Texture count
            spawn.PushInt(0);
            spawn.PushInt(TextureHands);
            spawn.PushInt(0);
            spawn.PushInt(1);
            spawn.PushInt(TextureBody);
            spawn.PushInt(0);
            spawn.PushInt(2);
            spawn.PushInt(TextureFeet);
            spawn.PushInt(0);
            spawn.PushInt(3);
            spawn.PushInt(TextureArms);
            spawn.PushInt(0);
            spawn.PushInt(4);
            spawn.PushInt(TextureLegs);
            spawn.PushInt(0);

            /// same as texture part, equip table should define the additional meshs
            /// data could be stored with the item entries

            spawn.Push3F1Count(AdditionalMeshs.Count);
            if (AdditionalMeshs.Count > 0)
            {
                // 0 head, 1 r_hand, 2 l_hand, 3 r_shoulder, 4 l_shoulder, 5 back, 6 hip, 7 r_thigh, 8 l_thigh, 9 r_crus, 10 l_crus, 11 r_arm, 12 l_arm, 13 r_forearm, 14 l_forearm
                for (counter=0;counter<AdditionalMeshs.Count;counter++)
                {
                    spawn.PushByte(AdditionalMeshs[counter].position);
                    spawn.PushInt(AdditionalMeshs[counter].meshvalue1);
                    spawn.PushInt(AdditionalMeshs[counter].meshvalue2);
                    spawn.PushByte(AdditionalMeshs[counter].priority);
                }
            }

            if (Weaponpairs.Count>0)
            {
                spawn.Push3F1Count(Weaponpairs.Count);
                for (counter = 0; counter < Weaponpairs.Count; counter++)
                {
                    spawn.PushInt(Weaponpairs[counter].value1);
                    spawn.PushInt(Weaponpairs[counter].value2);
                    spawn.PushInt(Weaponpairs[counter].value3);
                    spawn.PushInt(Weaponpairs[counter].value4);
                }
            }
            // Finishing output with 5byte 00
            spawn.PushInt(0);
            spawn.PushByte(0);
            
            byte[] spawnReply = spawn.Finish();
            
            // setting the packetflags
            spawnReply[30] = (byte)((packetflags>>24)&0xff);
            spawnReply[31] = (byte)((packetflags>>16)&0xff);
            spawnReply[32] = (byte)((packetflags>>8) & 0xff);
            spawnReply[33] = (byte)(packetflags & 0xff);
            cli.SendCompressed(spawnReply);
        }

        /// <summary>
        /// Spawns this NPC to every client in given playfield.
        /// </summary>
        /// <param name="playfield">Playfield to spawn to</param>
        public void SpawnToPlayfield(int playfield)
        {
            List<Client> mClients = Misc.FindClient.FindClientsByPF(Playfield);
            foreach (Client mClient in mClients)
            {
                SpawnToClient(mClient);
            }
        }

        /// <summary>
        /// Adds this NPC to server cache.
        /// </summary>
        public void AddToCache()
        {
            Program.zoneServer.Monsters.Add(this);
        }

        /// <summary>
        /// Removes this NPC from server cache.
        /// </summary>
        public void RemoveFromCache()
        {
            Program.zoneServer.Monsters.Remove(this);
        }

        /// <summary>
        /// Writes this NPC to SQL database.
        /// </summary>
        public void AddToDB()
        {
            string temp = "";
            int counter;
            string sqlQuery = "INSERT INTO `mobspawns` VALUES (";
            sqlQuery += string.Format("'{0}',", ID);
            sqlQuery += string.Format("'{0}',", Playfield);
            sqlQuery += String.Format(System.Globalization.CultureInfo.InvariantCulture, "'{0}',", coord.x);
            sqlQuery += String.Format(System.Globalization.CultureInfo.InvariantCulture, "'{0}',", coord.y);
            sqlQuery += String.Format(System.Globalization.CultureInfo.InvariantCulture, "'{0}',", coord.z);
            sqlQuery += String.Format(System.Globalization.CultureInfo.InvariantCulture, "'{0}',", heading.xf);
            sqlQuery += String.Format(System.Globalization.CultureInfo.InvariantCulture, "'{0}',", heading.yf);
            sqlQuery += String.Format(System.Globalization.CultureInfo.InvariantCulture, "'{0}',", heading.zf);
            sqlQuery += String.Format(System.Globalization.CultureInfo.InvariantCulture, "'{0}',", heading.wf);
            sqlQuery += string.Format("'{0}',", Side);
            sqlQuery += string.Format("'{0}',", Fatness);
            sqlQuery += string.Format("'{0}',", Breed);
            sqlQuery += string.Format("'{0}',", Sex);
            sqlQuery += string.Format("'{0}',", Race);
            sqlQuery += string.Format("'{0}',", Name);
            sqlQuery += string.Format("'{0}',", Flags);
            sqlQuery += string.Format("'{0}',", NPCFamily);
            sqlQuery += string.Format("'{0}',", Level);
            sqlQuery += string.Format("'{0}',", Health);
            sqlQuery += string.Format("'{0}',", MonsterData);
            sqlQuery += string.Format("'{0}',", MonsterScale);
            sqlQuery += string.Format("'{0}',", TextureHands);
            sqlQuery += string.Format("'{0}',", TextureBody);
            sqlQuery += string.Format("'{0}',", TextureFeet);
            sqlQuery += string.Format("'{0}',", TextureArms);
            sqlQuery += string.Format("'{0}',", TextureLegs);
            sqlQuery += string.Format("'{0}',", HeadMesh);
            sqlQuery += string.Format("'{0}',", LOSHeight);
            sqlQuery += string.Format("'{0}',", Runspeed);

            byte[] tempb;
            for (counter = 0; counter < Waypoints.Count; counter++)
            {
                tempb = BitConverter.GetBytes(Waypoints[counter].x);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
                tempb = BitConverter.GetBytes(Waypoints[counter].y);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
                tempb = BitConverter.GetBytes(Waypoints[counter].z);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
            }
            temp = "X'" + temp+"'";
            if (temp == "X''")
            {
                temp = "''";
            }
            sqlQuery += temp + ",";
            
            temp = "";
            for (counter = 0; counter < Weaponpairs.Count; counter++)
            {
                tempb = BitConverter.GetBytes(Weaponpairs[counter].value1);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
                tempb = BitConverter.GetBytes(Weaponpairs[counter].value2);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
                tempb = BitConverter.GetBytes(Weaponpairs[counter].value3);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
                tempb = BitConverter.GetBytes(Weaponpairs[counter].value4);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
            }
            temp = "X'" + temp+"'";
            if (temp == "X''")
            {
                temp = "''";
            }
            sqlQuery += temp + ",";
            temp = "";

            for (counter = 0; counter < RunningNanos.Count; counter++)
            {
                tempb = BitConverter.GetBytes(RunningNanos[counter].Nanotype);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
                tempb = BitConverter.GetBytes(RunningNanos[counter].Instance);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
                tempb = BitConverter.GetBytes(RunningNanos[counter].Value3);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
                tempb = BitConverter.GetBytes(RunningNanos[counter].Time1);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
                tempb = BitConverter.GetBytes(RunningNanos[counter].Time2);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
            }
            temp = "X'" + temp+"'";
            if (temp == "X''")
            {
                temp = "''";
            }
            sqlQuery += temp + ",";
            temp = "";

            for (counter = 0; counter < MobMeshs.Count; counter++)
            {
                tempb = BitConverter.GetBytes(MobMeshs[counter].Meshvalue1);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
                tempb = BitConverter.GetBytes(MobMeshs[counter].Meshvalue2);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
                tempb = BitConverter.GetBytes(MobMeshs[counter].Meshvalue3);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
            }

            temp = "X'" + temp+"'";
            if (temp == "X''")
            {
                temp = "''";
            }
            sqlQuery += temp + ",";
            temp = "";
            for (counter = 0; counter < AdditionalMeshs.Count; counter++)
            {
                temp += Convert.ToString(AdditionalMeshs[counter].position, 16).PadLeft(2, '0');
                tempb = BitConverter.GetBytes(AdditionalMeshs[counter].meshvalue1);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
                tempb = BitConverter.GetBytes(AdditionalMeshs[counter].meshvalue2);
                temp += Convert.ToString(tempb[0], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[1], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[2], 16).PadLeft(2, '0');
                temp += Convert.ToString(tempb[3], 16).PadLeft(2, '0');
                temp += Convert.ToString(AdditionalMeshs[counter].priority, 16).PadLeft(2, '0');
            

            }

            temp = "X'" + temp+"'";
            if (temp == "X''")
            {
                temp = "''";
            }
            sqlQuery += temp + ");";

// for debug only
//            Console.WriteLine(sqlQuery);  
            

            MySqlWrapper msql = new MySqlWrapper();
            try
            {
                msql.MySqlInsert(sqlQuery);
            }
            catch {
                Console.WriteLine("ERROR!!!");
            }
            msql.mcc.Close();
        }

        /// <summary>
        /// Removes this NPC from SQL database.
        /// </summary>
        public void RemoveFromDB()
        {
            MySqlWrapper msql = new MySqlWrapper();
            msql.MySqlDelete(string.Format("DELETE FROM `mobspawns` WHERE (`ID` = {0});", this.ID));
            msql.mcc.Close();
        }
    }
}